"""
考试卷管理模块 - API视图
为试卷管理功能提供完整的API接口
"""
from rest_framework import viewsets, status, generics
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.shortcuts import get_object_or_404
from django.db import transaction
from django.db.models import Q
from django.utils import timezone
from django.http import HttpResponse
import json
import logging

from .models import (
    ExamPaperTemplate, ExamPaper, PaperSection, PaperQuestion,
    PaperAnalysis, PaperVersion
)
from .serializers import (
    ExamPaperTemplateSerializer, ExamPaperSerializer,
    PaperSectionSerializer, PaperQuestionSerializer,
    PaperAnalysisSerializer, PaperVersionSerializer,
    ExamPaperCreateSerializer, ExamPaperAutoGenerateSerializer,
    PaperAnalysisRequestSerializer, PaperVersionCreateSerializer
)
from .permissions import (
    CanManageExamPaper, CanViewExamPaper, CanManageTemplate,
    CanAccessPaperAnalysis
)

logger = logging.getLogger(__name__)


class ExamPaperTemplateViewSet(viewsets.ModelViewSet):
    """试卷模板视图集"""
    permission_classes = [IsAuthenticated, CanManageTemplate]
    filterset_fields = ['template_type', 'is_active', 'is_public']
    search_fields = ['name', 'description']
    ordering_fields = ['created_at', 'name', 'usage_count']
    ordering = ['-created_at']

    def get_queryset(self):
        """获取查询集"""
        queryset = ExamPaperTemplate.objects.all()

        # 非管理员只能看到自己的模板和公开模板
        if not self.request.user.is_admin_user:
            queryset = queryset.filter(
                Q(creator=self.request.user) | Q(is_public=True)
            ).distinct()

        return queryset.select_related('creator')

    def get_serializer_class(self):
        """返回序列化器"""
        return ExamPaperTemplateSerializer

    def perform_create(self, serializer):
        """创建时设置创建者"""
        serializer.save(creator=self.request.user)

    @action(detail=True, methods=['post'])
    def generate_paper(self, request, pk=None):
        """基于模板生成试卷"""
        template = self.get_object()

        serializer = ExamPaperAutoGenerateSerializer(data=request.data)
        if serializer.is_valid():
            try:
                # 创建新试卷
                paper = ExamPaper.objects.create(
                    title=serializer.validated_data['title'],
                    template=template,
                    paper_type='formal',
                    creator=request.user,
                    generation_method='template'
                )

                # 从模板生成试卷内容
                paper.generate_from_template(template, **serializer.validated_data.get('config', {}))

                return Response({
                    'message': '试卷生成成功',
                    'paper_id': paper.id,
                    'paper_title': paper.title,
                    'question_count': paper.question_count
                })

            except Exception as e:
                logger.error(f"基于模板生成试卷失败: {e}")
                return Response({
                    'error': f'生成试卷失败: {str(e)}'
                }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    @action(detail=True, methods=['post'])
    def clone(self, request, pk=None):
        """克隆模板"""
        template = self.get_object()

        new_name = request.data.get('name', f"{template.name}_副本")

        try:
            # 创建新模板
            new_template = ExamPaperTemplate.objects.create(
                name=new_name,
                description=template.description,
                template_type=template.template_type,
                template_config=template.template_config.copy(),
                default_duration=template.default_duration,
                default_total_score=template.default_total_score,
                default_passing_score=template.default_passing_score,
                creator=request.user,
                is_public=False  # 克隆的模板默认为私有
            )

            return Response({
                'message': '模板克隆成功',
                'template_id': new_template.id,
                'template_name': new_template.name
            })

        except Exception as e:
            logger.error(f"克隆模板失败: {e}")
            return Response({
                'error': f'克隆模板失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=True, methods=['post'])
    def set_public(self, request, pk=None):
        """设置模板公开状态"""
        template = self.get_object()

        if template.creator != request.user and not request.user.is_admin_user:
            return Response({
                'error': '没有权限修改此模板'
            }, status=status.HTTP_403_FORBIDDEN)

        is_public = request.data.get('is_public', True)
        template.is_public = is_public
        template.save(update_fields=['is_public'])

        action_text = "公开" if is_public else "私有"
        return Response({
            'message': f'模板已设置为{action_text}'
        })

    @action(detail=True, methods=['get'])
    def preview(self, request, pk=None):
        """预览模板"""
        template = self.get_object()

        # 返回模板的预览信息
        data = {
            'id': template.id,
            'name': template.name,
            'description': template.description,
            'template_type': template.template_type,
            'template_config': template.template_config,
            'default_duration': template.default_duration,
            'default_total_score': float(template.default_total_score),
            'usage_count': template.usage_count,
            'preview_questions': []  # 这里可以添加题目预览逻辑
        }

        return Response(data)


class ExamPaperViewSet(viewsets.ModelViewSet):
    """试卷视图集"""
    permission_classes = [IsAuthenticated]
    filterset_fields = ['paper_type', 'status', 'generation_method', 'is_public']
    search_fields = ['title', 'description', 'creator__real_name']
    ordering_fields = ['created_at', 'title', 'total_score', 'usage_count']
    ordering = ['-created_at']

    def get_queryset(self):
        """获取查询集"""
        queryset = ExamPaper.objects.all()

        # 根据用户角色过滤
        if self.request.user.is_student:
            # 学生只能看到已发布的公开试卷
            queryset = queryset.filter(
                status='published',
                is_public=True
            )
        elif self.request.user.is_teacher:
            # 教师可以看到自己创建的试卷和公开试卷
            queryset = queryset.filter(
                Q(creator=self.request.user) | Q(is_public=True)
            ).distinct()
        # 管理员可以看到所有试卷

        return queryset.select_related('creator', 'template', 'reviewer')

    def get_serializer_class(self):
        """根据操作选择序列化器"""
        if self.action == 'create':
            return ExamPaperCreateSerializer
        return ExamPaperSerializer

    def get_permissions(self):
        """根据操作选择权限"""
        if self.action in ['create', 'update', 'partial_update', 'destroy']:
            self.permission_classes = [IsAuthenticated, CanManageExamPaper]
        elif self.action in ['retrieve', 'list']:
            self.permission_classes = [IsAuthenticated, CanViewExamPaper]
        else:
            self.permission_classes = [IsAuthenticated]

        return super().get_permissions()

    def perform_create(self, serializer):
        """创建时设置创建者"""
        serializer.save(creator=self.request.user)

    @action(detail=True, methods=['post'])
    def analyze(self, request, pk=None):
        """分析试卷质量"""
        paper = self.get_object()

        try:
            # 创建或更新分析记录
            analysis, created = PaperAnalysis.objects.get_or_create(
                exam_paper=paper,
                defaults={
                    'analysis_status': 'pending'
                }
            )

            # 执行分析
            analysis.analyze()

            return Response({
                'message': '试卷分析完成',
                'analysis': {
                    'difficulty_distribution': analysis.difficulty_distribution,
                    'average_difficulty': float(analysis.average_difficulty) if analysis.average_difficulty else None,
                    'type_distribution': analysis.type_distribution,
                    'quality_score': float(analysis.quality_score) if analysis.quality_score else None,
                    'estimated_time': analysis.estimated_time,
                    'improvement_suggestions': analysis.improvement_suggestions
                }
            })

        except Exception as e:
            logger.error(f"试卷分析失败: {e}")
            return Response({
                'error': f'分析失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=True, methods=['post'])
    def publish(self, request, pk=None):
        """发布试卷"""
        paper = self.get_object()

        if paper.status != 'reviewed':
            return Response({
                'error': '只有已审核的试卷才能发布'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            paper.status = 'published'
            paper.save(update_fields=['status'])

            return Response({
                'message': '试卷发布成功'
            })

        except Exception as e:
            logger.error(f"发布试卷失败: {e}")
            return Response({
                'error': f'发布失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=True, methods=['post'])
    def review(self, request, pk=None):
        """审核试卷"""
        paper = self.get_object()

        if paper.status != 'draft':
            return Response({
                'error': '只有草稿状态的试卷才能审核'
            }, status=status.HTTP_400_BAD_REQUEST)

        review_notes = request.data.get('review_notes', '')
        is_approved = request.data.get('is_approved', False)

        try:
            if is_approved:
                paper.status = 'reviewed'
                paper.reviewer = request.user
                paper.reviewed_at = timezone.now()
                paper.review_notes = review_notes
                paper.save(update_fields=['status', 'reviewer', 'reviewed_at', 'review_notes'])
            else:
                paper.status = 'draft'
                paper.review_notes = review_notes
                paper.save(update_fields=['status', 'review_notes'])

            return Response({
                'message': '试卷审核完成',
                'status': paper.status
            })

        except Exception as e:
            logger.error(f"审核试卷失败: {e}")
            return Response({
                'error': f'审核失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=True, methods=['post'])
    def create_version(self, request, pk=None):
        """创建试卷版本"""
        paper = self.get_object()

        serializer = PaperVersionCreateSerializer(data=request.data)
        if serializer.is_valid():
            try:
                # 创建试卷快照
                paper_snapshot = {
                    'title': paper.title,
                    'description': paper.description,
                    'paper_type': paper.paper_type,
                    'question_config': paper.question_config,
                    'duration': paper.duration,
                    'total_score': float(paper.total_score),
                    'passing_score': float(paper.passing_score),
                    'questions': paper.questions
                }

                # 创建版本记录
                version = PaperVersion.objects.create(
                    exam_paper=paper,
                    version_number=serializer.validated_data['version_number'],
                    version_notes=serializer.validated_data.get('version_notes', ''),
                    paper_snapshot=paper_snapshot,
                    changes=serializer.validated_data.get('changes', []),
                    created_by=request.user,
                    is_current=True
                )

                return Response({
                    'message': '版本创建成功',
                    'version_id': version.id,
                    'version_number': version.version_number
                })

            except Exception as e:
                logger.error(f"创建试卷版本失败: {e}")
                return Response({
                    'error': f'创建版本失败: {str(e)}'
                }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    @action(detail=False, methods=['post'])
    def auto_generate(self, request):
        """自动生成试卷"""
        serializer = ExamPaperAutoGenerateSerializer(data=request.data)
        if serializer.is_valid():
            template_id = serializer.validated_data['template_id']

            try:
                template = ExamPaperTemplate.objects.get(id=template_id)

                # 创建新试卷
                paper = ExamPaper.objects.create(
                    title=serializer.validated_data['title'],
                    template=template,
                    paper_type='formal',
                    creator=request.user,
                    generation_method='auto'
                )

                # 从模板生成试卷
                paper.generate_from_template(template, **serializer.validated_data.get('config', {}))

                return Response({
                    'message': '自动生成试卷成功',
                    'paper_id': paper.id,
                    'paper_title': paper.title,
                    'question_count': paper.question_count
                })

            except ExamPaperTemplate.DoesNotExist:
                return Response({
                    'error': '模板不存在'
                }, status=status.HTTP_404_NOT_FOUND)
            except Exception as e:
                logger.error(f"自动生成试卷失败: {e}")
                return Response({
                    'error': f'生成失败: {str(e)}'
                }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    @action(detail=True, methods=['post'])
    def add_questions(self, request, pk=None):
        """添加题目到试卷"""
        paper = self.get_object()

        question_ids = request.data.get('question_ids', [])
        scores = request.data.get('scores', {})

        if not question_ids:
            return Response({
                'error': '请选择要添加的题目'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            from apps.question_bank.models import Question

            with transaction.atomic():
                for i, question_id in enumerate(question_ids):
                    question = Question.objects.get(id=question_id)

                    # 创建试卷题目记录
                    paper_question = PaperQuestion.objects.create(
                        exam_paper=paper,
                        question=question,
                        question_number=paper.question_count + i + 1,
                        score=scores.get(str(question_id), Decimal('1.00'))
                    )

                # 更新试卷题目列表
                paper.questions.extend(question_ids)
                paper.question_count += len(question_ids)
                paper.save(update_fields=['questions', 'question_count'])

            return Response({
                'message': f'已添加 {len(question_ids)} 道题目',
                'total_questions': paper.question_count
            })

        except Question.DoesNotExist:
            return Response({
                'error': '部分题目不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            logger.error(f"添加题目失败: {e}")
            return Response({
                'error': f'添加失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=True, methods=['post'])
    def export_paper(self, request, pk=None):
        """导出试卷"""
        paper = self.get_object()

        export_format = request.data.get('format', 'json')

        try:
            if export_format == 'json':
                # 导出JSON格式
                export_data = {
                    'paper_info': {
                        'title': paper.title,
                        'description': paper.description,
                        'paper_type': paper.paper_type,
                        'duration': paper.duration,
                        'total_score': float(paper.total_score),
                        'passing_score': float(paper.passing_score)
                    },
                    'questions': []
                }

                # 添加题目详情
                for paper_question in paper.paper_questions.all().select_related('question'):
                    question_data = {
                        'number': paper_question.question_number,
                        'title': paper_question.question.title,
                        'type': paper_question.question.type,
                        'content': paper_question.question.content,
                        'score': float(paper_question.score),
                        'options': getattr(paper_question.question, 'options', []),
                        'answer': getattr(paper_question.question, 'answer', ''),
                        'explanation': getattr(paper_question.question, 'explanation', '')
                    }
                    export_data['questions'].append(question_data)

                response = HttpResponse(
                    json.dumps(export_data, ensure_ascii=False, indent=2),
                    content_type='application/json'
                )
                response['Content-Disposition'] = f'attachment; filename="{paper.title}.json"'
                return response

            else:
                return Response({
                    'error': f'不支持的导出格式: {export_format}'
                }, status=status.HTTP_400_BAD_REQUEST)

        except Exception as e:
            logger.error(f"导出试卷失败: {e}")
            return Response({
                'error': f'导出失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class PaperSectionViewSet(viewsets.ModelViewSet):
    """试卷部分视图集"""
    permission_classes = [IsAuthenticated]
    filterset_fields = ['exam_paper']
    search_fields = ['name', 'description']
    ordering_fields = ['order', 'created_at']
    ordering = ['exam_paper', 'order']

    def get_queryset(self):
        """获取查询集"""
        queryset = PaperSection.objects.all()

        # 根据用户角色过滤
        if self.request.user.is_student:
            # 学生只能看到已发布试卷的部分
            queryset = queryset.filter(
                exam_paper__status='published',
                exam_paper__is_public=True
            )
        elif self.request.user.is_teacher:
            # 教师可以看到自己创建或公开的试卷的部分
            queryset = queryset.filter(
                Q(exam_paper__creator=self.request.user) | Q(exam_paper__is_public=True)
            ).distinct()

        return queryset.select_related('exam_paper')

    def get_serializer_class(self):
        """返回序列化器"""
        return PaperSectionSerializer

    @action(detail=True, methods=['post'])
    def reorder_questions(self, request, pk=None):
        """重新排序部分内的题目"""
        section = self.get_object()

        question_orders = request.data.get('question_orders', {})

        try:
            with transaction.atomic():
                for paper_question_id, new_order in question_orders.items():
                    PaperQuestion.objects.filter(
                        id=paper_question_id,
                        section=section
                    ).update(order=new_order)

            return Response({
                'message': '题目顺序更新成功'
            })

        except Exception as e:
            logger.error(f"重新排序题目失败: {e}")
            return Response({
                'error': f'排序失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class PaperQuestionViewSet(viewsets.ModelViewSet):
    """试卷题目视图集"""
    permission_classes = [IsAuthenticated]
    filterset_fields = ['exam_paper', 'section', 'question']
    search_fields = ['question__title', 'question__content']
    ordering_fields = ['question_number', 'order', 'score']
    ordering = ['exam_paper', 'order', 'question_number']

    def get_queryset(self):
        """获取查询集"""
        queryset = PaperQuestion.objects.all()

        # 根据用户角色过滤
        if self.request.user.is_student:
            # 学生只能看到已发布试卷的题目
            queryset = queryset.filter(
                exam_paper__status='published',
                exam_paper__is_public=True
            )
        elif self.request.user.is_teacher:
            # 教师可以看到自己创建或公开的试卷的题目
            queryset = queryset.filter(
                Q(exam_paper__creator=self.request.user) | Q(exam_paper__is_public=True)
            ).distinct()

        return queryset.select_related('exam_paper', 'section', 'question')

    def get_serializer_class(self):
        """返回序列化器"""
        return PaperQuestionSerializer

    @action(detail=True, methods=['post'])
    def update_score(self, request, pk=None):
        """更新题目分数"""
        paper_question = self.get_object()

        new_score = request.data.get('score')

        if new_score is None:
            return Response({
                'error': '请提供新的分数'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            paper_question.score = new_score
            paper_question.save(update_fields=['score'])

            # 重新计算试卷总分
            paper = paper_question.exam_paper
            total_score = paper.paper_questions.aggregate(
                total=Sum('score')
            )['total'] or 0

            paper.total_score = total_score
            paper.save(update_fields=['total_score'])

            return Response({
                'message': '题目分数更新成功',
                'new_score': float(new_score),
                'paper_total_score': float(total_score)
            })

        except Exception as e:
            logger.error(f"更新题目分数失败: {e}")
            return Response({
                'error': f'更新失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class PaperAnalysisViewSet(viewsets.ReadOnlyModelViewSet):
    """试卷分析视图集"""
    permission_classes = [IsAuthenticated, CanAccessPaperAnalysis]
    filterset_fields = ['analysis_status']
    ordering_fields = ['created_at', 'analyzed_at']
    ordering = ['-created_at']

    def get_queryset(self):
        """获取查询集"""
        # 只有管理员和试卷创建者可以查看分析
        queryset = PaperAnalysis.objects.all()

        if not self.request.user.is_admin_user:
            queryset = queryset.filter(
                exam_paper__creator=self.request.user
            )

        return queryset.select_related('exam_paper')

    def get_serializer_class(self):
        """返回序列化器"""
        return PaperAnalysisSerializer

    @action(detail=False, methods=['post'])
    def batch_analyze(self, request):
        """批量分析试卷"""
        paper_ids = request.data.get('paper_ids', [])

        if not paper_ids:
            return Response({
                'error': '请选择要分析的试卷'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            papers = ExamPaper.objects.filter(id__in=paper_ids)

            if not papers:
                return Response({
                    'error': '未找到指定的试卷'
                }, status=status.HTTP_404_NOT_FOUND)

            created_count = 0
            for paper in papers:
                analysis, created = PaperAnalysis.objects.get_or_create(
                    exam_paper=paper,
                    defaults={
                        'analysis_status': 'pending'
                    }
                )
                if created:
                    created_count += 1
                    # 异步执行分析
                    analysis.analyze()

            return Response({
                'message': f'已创建 {created_count} 个分析任务',
                'total_papers': len(paper_ids)
            })

        except Exception as e:
            logger.error(f"批量分析试卷失败: {e}")
            return Response({
                'error': f'批量分析失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class PaperVersionViewSet(viewsets.ReadOnlyModelViewSet):
    """试卷版本视图集"""
    permission_classes = [IsAuthenticated]
    filterset_fields = ['is_current']
    ordering_fields = ['created_at']
    ordering = ['-created_at']

    def get_queryset(self):
        """获取查询集"""
        # 只有管理员和试卷创建者可以查看版本
        queryset = PaperVersion.objects.all()

        if not self.request.user.is_admin_user:
            queryset = queryset.filter(
                created_by=self.request.user
            )

        return queryset.select_related('exam_paper', 'created_by')

    def get_serializer_class(self):
        """返回序列化器"""
        return PaperVersionSerializer

    @action(detail=True, methods=['post'])
    def restore(self, request, pk=None):
        """恢复到指定版本"""
        version = self.get_object()

        try:
            paper = version.exam_paper
            snapshot = version.paper_snapshot

            # 恢复试卷状态
            paper.title = snapshot['title']
            paper.description = snapshot.get('description', '')
            paper.question_config = snapshot.get('question_config', {})
            paper.duration = snapshot.get('duration', 120)
            paper.total_score = snapshot['total_score']
            paper.passing_score = snapshot.get('passing_score', 60)

            paper.save()

            return Response({
                'message': f'已恢复到版本 {version.version_number}'
            })

        except Exception as e:
            logger.error(f"恢复试卷版本失败: {e}")
            return Response({
                'error': f'恢复失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=True, methods=['post'])
    def compare_with_current(self, request, pk=None):
        """与当前版本比较"""
        version = self.get_object()

        try:
            paper = version.exam_paper
            snapshot = version.paper_snapshot

            # 比较差异
            differences = {
                'title_changed': snapshot['title'] != paper.title,
                'description_changed': snapshot.get('description', '') != paper.description,
                'duration_changed': snapshot.get('duration', 120) != paper.duration,
                'total_score_changed': snapshot['total_score'] != paper.total_score,
                'passing_score_changed': snapshot.get('passing_score', 60) != paper.passing_score,
            }

            # 计算题目变化
            old_questions = set(snapshot.get('questions', []))
            current_questions = set(paper.questions)
            differences['questions_added'] = list(current_questions - old_questions)
            differences['questions_removed'] = list(old_questions - current_questions)
            differences['questions_changed'] = len(differences['questions_added']) + len(differences['questions_removed'])

            return Response({
                'version_info': {
                    'version_number': version.version_number,
                    'created_at': version.created_at,
                    'created_by': version.created_by.real_name
                },
                'differences': differences
            })

        except Exception as e:
            logger.error(f"比较试卷版本失败: {e}")
            return Response({
                'error': f'比较失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)